﻿// Copyright (c) 2007-2020 西安交通信息投资营运有限公司 版权所有
// 作者:吕艳阳

using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using DevExpress.XtraSplashScreen;

namespace XCI.Core
{
    /// <summary>
    /// Loading面板
    /// </summary>
    public class LoadingMask
    {
        private Control _owner;
        private OverlayWindowOptions _options;
        private IOverlaySplashScreenHandle _handle;

        /// <summary>
        /// 加载提示面板默认选项
        /// </summary>
        public static OverlayWindowOptions DefaultOverlayWindowOptions { get; set; } = new OverlayWindowOptions { AnimationType = WaitAnimationType.Image };

        /// <summary>
        /// 初始化Loading面板
        /// </summary>
        public LoadingMask()
        {
        }

        /// <summary>
        /// 初始化Loading面板
        /// </summary>
        /// <param name="owner">Loading面板显示的目标控件</param>
        public LoadingMask(Control owner) : this(owner, null)
        {
        }

        /// <summary>
        /// 初始化Loading面板
        /// </summary>
        /// <param name="options">Loading面板显示选项</param>
        public LoadingMask(OverlayWindowOptions options) : this(null, options)
        {
        }

        /// <summary>
        /// 初始化Loading面板
        /// </summary>
        /// <param name="owner">Loading面板显示的目标控件</param>
        /// <param name="options">Loading面板显示选项</param>
        public LoadingMask(Control owner, OverlayWindowOptions options)
        {
            _owner = owner;
            _options = options;
        }

        public Control Owner => _owner;
        private OverlayWindowOptions Options => _options;

        /// <summary>
        /// 新创建Loading面板
        /// </summary>
        public static LoadingMask Create()
        {
            return new LoadingMask();
        }

        /// <summary>
        /// 新创建Loading面板
        /// </summary>
        /// <param name="owner">Loading面板显示的目标控件</param>
        public static LoadingMask Create(Control owner)
        {
            return new LoadingMask(owner);
        }

        /// <summary>
        /// 新创建Loading面板
        /// </summary>
        /// <param name="options">Loading面板显示选项</param>
        public static LoadingMask Create(OverlayWindowOptions options)
        {
            return new LoadingMask(options);
        }

        /// <summary>
        /// 新创建Loading面板
        /// </summary>
        /// <param name="owner">Loading面板显示的目标控件</param>
        /// <param name="options">Loading面板显示选项</param>
        public static LoadingMask Create(Control owner, OverlayWindowOptions options)
        {
            return new LoadingMask(owner, options);
        }

        /// <summary>
        /// 显示Loading面板
        /// </summary>
        public void Show()
        {
            Show(null, null);
        }

        /// <summary>
        /// 显示Loading面板
        /// </summary>
        /// <param name="owner">Loading面板显示的目标控件</param>
        public void Show(Control owner)
        {
            Show(owner, null);
        }

        /// <summary>
        /// 显示Loading面板
        /// </summary>
        /// <param name="options">Loading面板显示选项</param>
        public void Show(OverlayWindowOptions options)
        {
            Show(null, options);
        }

        /// <summary>
        /// 显示Loading面板
        /// </summary>
        /// <param name="owner">Loading面板显示的目标控件</param>
        /// <param name="options">Loading面板显示选项</param>
        public void Show(Control owner, OverlayWindowOptions options)
        {
            if (_handle != null) return;
            if (owner != null) _owner = owner;
            if (options != null) _options = options;
            if (_owner.IsHandleCreated == false) return;

            if (_owner == null) throw new ArgumentNullException(nameof(owner), "请指定Loading面板显示的目标控件");

            _handle = SplashScreenManager.ShowOverlayForm(_owner, _options ?? DefaultOverlayWindowOptions);
        }

        /// <summary>
        /// 隐藏Loading面板
        /// </summary>
        public void Hide()
        {
            if (_handle == null) return;

            _handle.Close();
            _handle = null;
        }

        /// <summary>
        /// 使用Loading面板包装执行函数,执行前显示加载框,执行后隐藏加载框
        /// </summary>
        /// <param name="callback">执行函数</param>
        public void Show(Action callback)
        {
            if (callback == null) throw new ArgumentNullException(nameof(callback));
            try
            {
                Show();
                callback();
            }
            finally
            {
                Hide();
            }
        }

        /// <summary>
        /// 使用Loading面板包装异步执行函数,执行前显示加载框,执行后隐藏加载框
        /// </summary>
        /// <param name="callback">执行函数</param>
        public async Task ShowAsync(Func<Task> callback)
        {
            if (callback == null) throw new ArgumentNullException(nameof(callback));
            try
            {
                if (_owner is Form) await Task.Delay(10);
                Show();
                await callback();
            }
            finally
            {
                Hide();
            }
        }

        /// <summary>
        /// 使用Loading面板包装异步执行函数,执行前显示加载框,执行后隐藏加载框
        /// </summary>
        /// <param name="owner">Loading面板显示的目标控件</param>
        /// <param name="callback">执行函数</param>
        public async Task ShowAsync(Control owner, Func<Task> callback)
        {
            if (callback == null) throw new ArgumentNullException(nameof(callback));
            try
            {
                if (owner is Form) await Task.Delay(10);
                Show(owner);
                await callback();
            }
            finally
            {
                Hide();
            }
        }
    }
}